/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import edu.cmu.lti.sepia.infra.Pair;

public class IOUtil {

  public static String readFile(String filePath) throws IOException {
    String result = null;
    FileInputStream fis = null;
    File file = new File(filePath);
    try {
      if (!file.exists()) throw new FileNotFoundException();
      fis = new FileInputStream(file);
      result = readFromStream(fis);
    } catch (FileNotFoundException e1) {
      throw new IOException("required file not found at " + file.getAbsolutePath());
    } catch (IOException e2) {
      throw new IOException("cannot read " + file.getAbsolutePath());
    } finally {
      if (fis!=null){ 
        fis.close();
      }
    }
    return result;
  }

  public static String readResource(String fileName) throws IOException {
    try {
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      InputStream is = cl.getResourceAsStream(fileName);
      return readFromStream(is);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
  
  private static String readFromStream( InputStream is ) throws IOException {
    StringBuilder sb = new StringBuilder();
    InputStreamReader reader = new InputStreamReader( is, "utf8" );
    BufferedReader br = new BufferedReader( reader ); 
    String line = null;
    while ( ( line=br.readLine() )!=null ) {
      sb.append( line+"\n");
    }
    br.close();
    reader.close();
    return sb.toString();
  }
  
  public static List<String> readOneTuples(String filePath) throws IOException {
    List<String> result = new ArrayList<String>();
    String fileContent = IOUtil.readFile(filePath);
    String[] lines = fileContent.split("\n");
    for (String line : lines) {
      line = line.trim();
      if (line.length() == 0 || line.startsWith("#")) continue;
      result.add(line);
    }
    return result;
  }

  public static List<Pair<String, String>> readTwoTuples(String filePath) throws IOException {
    List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
    String fileContent = IOUtil.readFile(filePath);
    String[] lines = fileContent.split("\n");
    for (String line : lines) {
      line = line.trim();
      if (line.length() == 0 || line.startsWith("#")) continue;
      String[] items = line.split(",");
      if (items.length != 2) continue;
      Pair<String, String> pair = new Pair<String, String>(items[0], items[1]);
      result.add(pair);
    }
    return result;
  }
  
  public static byte[] getByteArrayFromFile(File file) throws IOException {
    InputStream is = null;
    byte[] bytes;
    try {
      is = new FileInputStream(file);
      long length = file.length();
  
      bytes = new byte[(int) length];
  
      int offset = 0;
      int numRead = 0;
      while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
        offset += numRead;
      }
  
      if (offset < bytes.length) {
        throw new IOException("Could not completely read file " + file.getName());
      }
    } finally {
      if (is!=null) {
        is.close();
      }
    }
    
    return bytes;
  }

  public static void appendToFile(String content, File file) throws IOException {
    writeToFile(content, file, true);
  }
  
  public static void writeToFile(String content, File file) throws IOException {
    writeToFile(content, file, false);
  }
  
  private static void writeToFile(String content, File file, boolean append) throws IOException {
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream( file, append );
      writeToStream(content, fos);
    } catch (IOException e2) {
      throw new IOException("cannot write to " + file.getAbsolutePath());
    } finally {
      if (fos!=null){ 
        fos.close();
      }
    }
  }
  
  private static void writeToStream( String content, OutputStream os ) throws IOException {
    OutputStreamWriter writer = new OutputStreamWriter( os, "utf-8" );
    BufferedWriter bw = new BufferedWriter( writer );
    bw.write(content);
    bw.close();
    writer.close();
  }
  
  //TODO: Write it in more sophisticated way
  private static File findResourceAndSave(String fileName) throws IOException {
    try {
      String date = new SimpleDateFormat("yyyyMMdd-HHmmss").format(Calendar.getInstance().getTime());
      int pos = fileName.indexOf(".");
      String name = fileName.substring(0,pos);
      String ext = fileName.substring(pos);
      File tempFile = new File(System.getProperty("java.io.tmpdir")+"/"+name+"-"+date+ext);
      
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      InputStream is = cl.getResourceAsStream(fileName);
      FileOutputStream fos = new FileOutputStream(tempFile);
      OutputStreamWriter osw = new OutputStreamWriter(fos);
      BufferedWriter bw = new BufferedWriter(osw);
     
      InputStreamReader isr = new InputStreamReader( is, "utf8" );
      BufferedReader br = new BufferedReader( isr ); 
      String line = null;
      while ( ( line=br.readLine() )!=null ) {
        bw.write( line+"\n");
      }
      bw.close();
      br.close();
      is.close();
      isr.close();
      osw.close();
      fos.close();
      
      return tempFile;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }
}
